/*
 * Copyright (c) 2004-2005, Volatile-Engine All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the Volatile-Engine nor the
 * names of its contributors may be used to endorse or promote products derived
 * from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 */
package com.volatileengine.scene;

import javax.vecmath.Color4f;
import javax.vecmath.Point3f;
import javax.vecmath.Vector2f;
import javax.vecmath.Vector3f;

import com.volatileengine.datatypes.AbstractArray;
import com.volatileengine.datatypes.ArrayElement;
import com.volatileengine.datatypes.ArrayInt;
import com.volatileengine.datatypes.InterleavedArrayFloat;

/**
 * @author Ahmed
 */
public class InterleavedGeometry extends Geometry {

	protected AbstractArray<?> parentArray;
	protected ArrayElement<?> vertices;
	protected ArrayElement<?> normals;
	protected ArrayElement<?> colours;
	protected ArrayElement<?>[] texture;

	protected AbstractArray<?> indices;

	public InterleavedGeometry() {
		super();
	}

	public InterleavedGeometry(int vertexSize, int normalSize, int colourSize, int[] textureSize, int triangles) {
		this(vertexSize, normalSize, colourSize, textureSize, new ArrayInt(3, triangles));
	}

	public InterleavedGeometry(int vertexSize, int normalSize, int colourSize, int[] textureSize,
			AbstractArray<?> indices) {
		int[] sizes = new int[textureSize.length + 3];
		sizes[0] = vertexSize;
		int pos = 1;
		if (normalSize > 0) {
			sizes[pos++] = normalSize;
		}
		if (colourSize > 0) {
			sizes[pos++] = colourSize;
		}
		for (int i = 0; i < textureSize.length; i++) {
			if (textureSize[i] > 0) {
				sizes[pos++] = textureSize[i];
			}
		}

		parentArray = new InterleavedArrayFloat(sizes, 0, pos);

		vertices = parentArray.getChildAt(0);
		pos = 1;
		if (normalSize > 0) {
			normals = parentArray.getChildAt(pos++);
		}
		if (colourSize > 0) {
			colours = parentArray.getChildAt(pos++);
		}

		int texCount = parentArray.getChildCount() - pos;
		texture = new ArrayElement<?>[texCount];

		for (int i = 0; i < texCount; i++) {
			texture[i] = parentArray.getChildAt(pos + i);
		}

		this.indices = indices;
	}

	public InterleavedGeometry(Point3f[] verticesA, Vector3f[] normalsA, Color4f[] colorsA,
			Vector2f[][] textureCoordinatesA, int[] indicesA) {
		int sizeArraySize = 3 + (textureCoordinatesA == null ? 0 : textureCoordinatesA.length);
		int[] sizes = new int[sizeArraySize];
		int pos = 0;
		sizes[pos++] = 3;// vertices
		if (normalsA != null) {
			sizes[pos++] = 3;// normals
		}
		if (colorsA != null) {
			sizes[pos++] = 4; // colours
		}
		if (textureCoordinatesA != null) {
			for (int i = 0; i < textureCoordinatesA.length; i++) {
				sizes[pos++] = 2;
			}
		}

		parentArray = new InterleavedArrayFloat(sizes, verticesA.length, pos);

		int children = 0;
		vertices = parentArray.getChildAt(children++);
		if (normalsA != null) {
			normals = parentArray.getChildAt(children++);
		}

		if (colorsA != null) {
			colours = parentArray.getChildAt(children++);
		}

		if (textureCoordinatesA != null) {
			texture = new ArrayElement[textureCoordinatesA.length];
			for (int i = 0; i < texture.length; i++) {
				texture[i] = parentArray.getChildAt(children++ + i);
			}
		}
		indices = new ArrayInt(1, indicesA.length);

		setupGeometry(verticesA, normalsA, colorsA, textureCoordinatesA, indicesA);
	}

	/**
	 * @return Returns the colours.
	 */
	@Override
	public ArrayElement<?> getColours() {
		return colours;
	}

	/**
	 * @return Returns the indices.
	 */
	@Override
	public AbstractArray<?> getIndices() {
		return indices;
	}

	/**
	 * @return Returns the normals.
	 */
	@Override
	public ArrayElement<?> getNormals() {
		return normals;
	}

	/**
	 * @return Returns the texture.
	 */
	@Override
	public ArrayElement<?>[] getTextureCoordinates() {
		return texture;
	}

	/**
	 * @return Returns the vertices.
	 */
	@Override
	public ArrayElement<?> getVertices() {
		return vertices;
	}

	@Override
	public int getVertexQuantity() {
		return parentArray.getLength();
	}

	public AbstractArray<?> getParentArray() {
		return parentArray;
	}

	/**
	 * @param array
	 *             The array to set.
	 */
	public void setParentArray(AbstractArray<?> array) {
		this.parentArray = array;
	}

	/**
	 * @param colours
	 *             The colours to set.
	 */
	public void setColours(ArrayElement<?> colours) {
		this.colours = colours;
	}

	/**
	 * @param indices
	 *             The indices to set.
	 */
	public void setIndices(AbstractArray<?> indices) {
		this.indices = indices;
	}

	/**
	 * @param normals
	 *             The normals to set.
	 */
	public void setNormals(ArrayElement<?> normals) {
		this.normals = normals;
	}

	/**
	 * @param texture
	 *             The texture to set.
	 */
	public void setTextureCoordinates(ArrayElement<?>[] texture) {
		this.texture = texture;
	}

	/**
	 * @param vertices
	 *             The vertices to set.
	 */
	public void setVertices(ArrayElement<?> vertices) {
		this.vertices = vertices;
	}
}
